<?php
/**
 * Created by PhpStorm.
 * User: insgeek
 * Date: 2017/2/14
 * Time: 9:43
 * 建造者模式
 */
namespace DesignPattern\BuilderPattern;

interface Item
{
    public function name():string ;

    public function packing():Packing;

    public function price():float ;

}

interface Packing
{
    public function pack(): string;
}

class Wrapper implements Packing
{
    public function pack(): string
    {
        // TODO: Implement pack() method.
        return "Wrapper";
    }
}

class Bottle implements Packing
{
    public function pack(): string
    {
        // TODO: Implement pack() method.
        return "Bottle";
    }
}

abstract class Burger implements Item
{
    public function packing(): Packing
    {
        // TODO: Implement packing() method.
        return new Wrapper();
    }

    public abstract function price():float ;

}

abstract class ColdDrink implements Item
{
    public function packing(): Packing
    {
        // TODO: Implement packing() method.
        return new Bottle();
    }
}

class VegBurger extends Burger
{
    public function price() :float
    {

        // TODO: Implement price() method.
        return 25.0;
    }

    public function name(): string
    {
        // TODO: Implement name() method.
        return "Veg Burger";
    }
}

class ChickenBurger extends Burger
{
    public function price() :float
    {

        // TODO: Implement price() method.
        return 50.5;
    }

    public function name(): string
    {
        // TODO: Implement name() method.
        return "Chicken Burger";
    }
}

class Coke extends ColdDrink
{
    public function price() :float
    {

        // TODO: Implement price() method.
        return 30.0;
    }

    public function name(): string
    {
        // TODO: Implement name() method.
        return "Coke";
    }
}


class Pepsi extends ColdDrink
{
    public function price() :float
    {

        // TODO: Implement price() method.
        return 35.0;
    }

    public function name(): string
    {
        // TODO: Implement name() method.
        return "Pepsi";
    }
}

class Meal
{
    private $items = [];

    public function addItem(Item $item)
    {
        $this->items[] = $item;
    }

    public function getCost()
    {
        $cost = 0.0;
        foreach ($this->items as $k) {
            $cost += $k->price();
        }
        return $cost;
    }

    public function showItems()
    {
        foreach ($this->items as $k) {
            echo "Item:", $k->name(),
            ";  Packing:", $k->packing()->pack(),
            ";  Price:", $k->price(),PHP_EOL;
        }
    }
}

class MealBuilder
{
    public function prepareVegMel():Meal
    {
        $meal = new Meal();
        $meal->addItem(new VegBurger());
        $meal->addItem(new Coke());
        return $meal;
    }

    public function prepareNonVeMeal():Meal
    {
        $meal = new Meal();
        $meal->addItem(new ChickenBurger());
        $meal->addItem(new Pepsi());
        return $meal;
    }
}

$mealBuilder = new MealBuilder();
$vegMeal = $mealBuilder->prepareVegMel();
echo 'Veg Meal', PHP_EOL;
$vegMeal->showItems();
echo "Total Cost:", $vegMeal->getCost(),PHP_EOL;
$nonVegMeal = $mealBuilder->prepareNonVeMeal();
echo 'Non-Veg Meal', PHP_EOL;
$nonVegMeal->showItems();
echo "Total Cost:", $nonVegMeal->getCost(),PHP_EOL;